package com.gjm.tool.paramHandle;

import com.alibaba.fastjson.JSON;
import com.gjm.tool.modifyLog.service.IModifyHistoryLogService;
import com.gjm.tool.sign.SignEnum;
import com.gjm.tool.sign.SignUtil;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 通过Aop的方式实现接口参数验证
 */
@Order(2)
@Aspect
@Component
public class ParamHandleAspect {

    private static final Logger log = LoggerFactory.getLogger(ParamHandleAspect.class);

    //同一个请求多长时间内有效 10分钟
    private static final List<String> FIELD_LIST = Arrays.asList("paramField", "account_name", "account_type", "business_name", "business_code", "creator");

    @Resource
    private IModifyHistoryLogService modifyHistoryLogService;


    /**
     * 拦截校验相关接口
     */
    @Around("@annotation(paramHandle)")
    public Object doAround(ProceedingJoinPoint pjp, ParamHandle paramHandle) throws Throwable {
        try {
            List<String> fieldList = new ArrayList<>();
            //method方法
            String methodName = ((MethodSignature) pjp.getSignature()).getMethod().getName();
            switch (methodName) {
                case "testSign":
                    fieldList = modifyHistoryLogService.getFields("modify_history_log");
                case "updateById":
                    break;
                default:
                    break;
            }
            //方法的形参参数
            Object[] args = pjp.getArgs();
            List<String> checkList = fieldList;
            //获取目标参数
            for (String paramName : paramHandle.paramNames()) {
                Field paramField = getField(args[0], paramName);
                paramField.setAccessible(true);
                //只接受数组传参
                List<String> paramList = (List<String>) paramField.get(args[0]);
                List<String> resultList = paramList.stream().filter(i -> checkList.contains(i)).collect(Collectors.toList());
                paramField.set(args[0], resultList);
                log.info("参数处理完毕,处理前:{},处理后参数:{}", JSON.toJSONString(paramList), JSON.toJSONString(resultList));
                List<String> list = (List<String>) paramField.get(args[0]);
                System.out.println(JSON.toJSONString(list));
            }
            return pjp.proceed();
        } catch (Throwable e) {
            throw e;
        }
    }


    /**
     * 通过反射获Field
     *
     * @param lstDatum  对象
     * @param fieldName 字段名
     * @param <T>
     * @return 字段名所对应的F
     */
    public <T> Field getField(T lstDatum, String fieldName) {
        if (lstDatum == null || StringUtils.isBlank(fieldName)) {
            return null;
        }
        Field field = null;
        Class<?> clazz = lstDatum.getClass();
        for (; clazz != Object.class; clazz = clazz.getSuperclass()) {
            try {
                field = clazz.getDeclaredField(fieldName);
                return field;
            } catch (Exception e) {
                //这里甚么都不要做！并且这里的异常必须这样写，不能抛出去。
                //如果这里的异常打印或者往外抛，则就不会执行clazz = clazz.getSuperclass(),最后就不会进入到父类中了
            }
        }
        return null;
    }
}